#ifndef RENDER_VIEW_H
#define RENDER_VIEW_H

#include <memory>

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
#include <QMatrix4x4>
#include <QMutex>

// QOpenGL 相关
class QOffscreenSurface;

class RenderManager;
class QWaitCondition;
class Renderer;

/**
 * @brief The RenderView class 渲染界面类
 *
 * 通过 addRenderer 添加渲染模型
 */
class RenderView : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT

    friend class RenderManager;

public:
    explicit RenderView(QWidget *parent = nullptr);
    ~RenderView();

    virtual bool eventFilter(QObject *watched, QEvent *event) override;

    void addRenderer(std::shared_ptr<Renderer> renderer);

    bool paintEnabled() const;
    void setPaintEnabled(bool paint_enabled);

    /// 替换 QWidget::grab 接口
    /// 线程化渲染情况下, 原生 grab 获取不到渲染结果
    Q_INVOKABLE QPixmap grab(const QRect &rectangle = QRect(QPoint(0, 0),
                                                            QSize(-1, -1)));

protected:
    virtual void initializeGL() override;
    /// 处理窗口大小变化
    virtual void resizeGL(int w, int h) override;
    /// 绘制 OpenGL 场景
    virtual void paintGL() override;
    /// 定时刷新
    virtual void timerEvent(QTimerEvent *event) override;
    ///
    virtual void paintEvent(QPaintEvent *event) override;

    /// 设置刷新时间间隔
    void setUpdateInterval(int interval);

private:
    void refresh(QWidget *wd);

private Q_SLOTS:
    /// 双缓冲机制：子线程绘制耗时再长，都不会阻塞 ui 线程。
    /// 将子线程的帧缓冲区拷贝到 QOpenGLWidget 处理。
    void onBlitFramebuffer();

protected:
    std::shared_ptr<RenderManager> render_manager_{ nullptr }; ///< 渲染器

    bool update_enabled_{ true }; ///< 刷新使能，子线程渲染期间禁用

private:
    QOffscreenSurface *surface_{ nullptr }; ///< 离屏渲染

    int update_timer_id_{ 0 }; ///< 刷新间隔时间

    bool paint_enabled_{ true }; ///< 绘制使能, 开放给外部操控

    bool grabbing_{ false }; ///< grab() 标记
};

#endif // RENDER_VIEW_H
